#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hwicodec_common.h>
#ifdef DMALLOC
#include <imp/dmalloc.h>
#endif
int hwicodec_validate_common_parameters(hwicodec_t *h)
{
	hwicodec_param_t *param = &h->param;
	if ((param->protocol < C_H264E) || (param->protocol >= C_PROT_MAX)) {
		hwicodec_log(h, C_LOG_ERROR, "protocol:%d is invalidate\n", param->protocol);
		goto err_protocol;
	}

	if ((param->soc < C_M200) || (param->soc >= C_SOC_MAX)) {
		hwicodec_log(h, C_LOG_ERROR, "soc:%d is invalidate\n", param->soc);
		goto err_soc;
	}

	if ((param->i_log_level < C_LOG_NONE) || (param->i_log_level > C_LOG_DEBUG)) {
		hwicodec_log(h, C_LOG_WARNING, "i_log_level:%d set to NONE\n", param->i_log_level);
		goto err_log_level;
	}
	if (!param->ckmalloc || !param->ckfree || !param->ckvirt_to_phys || !param->ckphys_to_virt) {
		hwicodec_log(h, C_LOG_WARNING, "memory management func is NULL\n");
		goto err_malloc_free;
	}

	return 0;

err_malloc_free:
err_log_level:
err_soc:
err_protocol:
	return -1;
}

static int hwicodec_pf_init(hwicodec_t *h, hwicodec_func_t *pf, int protocol, int soc)
{
	hwicodec_func_t *pfi = NULL;
	pfi = pf_array[protocol][soc];
	if (!pfi->init || !pfi->deinit || !pfi->process || !pfi->request_vbinfo || !pfi->release_vbinfo
		|| !pfi->validate_parameters) {
		hwicodec_log(h, C_LOG_ERROR, "pf_array[%d][%d] is NULL\n", protocol, soc);
		goto err_pf_array;
	}
	*pf = *pfi;

	return 0;

err_pf_array:
	return -1;
}

hwicodec_t *hwicodec_init(hwicodec_param_t *param)
{
	hwicodec_t *h = NULL;

	if ((h = malloc(sizeof(hwicodec_t))) == NULL) {
		hwicodec_log(NULL, C_LOG_ERROR, "malloc hwicodec failed\n");
		goto err_malloc_hwicodec;
	}
	memset(h, 0, sizeof(hwicodec_t));
	memcpy(&h->param, param, sizeof(hwicodec_param_t));

	if(hwicodec_validate_common_parameters(h) < 0) {
		hwicodec_log(NULL, C_LOG_ERROR, "validate_common_parameters failed\n");
		goto err_validate_common_parameters;
	}

	if (hwicodec_pf_init(h, &h->pf, h->param.protocol, h->param.soc) < 0) {
		hwicodec_log(NULL, C_LOG_ERROR, "hwicodec_pf_init failed\n");
		goto err_pf_init;
	}

	if (h->pf.validate_parameters(h) < 0) {
		hwicodec_log(NULL, C_LOG_ERROR, "validate_parameters failed\n");
		goto err_validate_parameters;
	}

	if (h->pf.init(h) < 0) {
		hwicodec_log(NULL, C_LOG_ERROR, "init failed\n");
		goto err_init;
	}
    if (h->param.protocol == C_H264E)
        param->param.h264e_param.H264E_SliceInfoSize = h->param.param.h264e_param.H264E_SliceInfoSize;
    else if (h->param.protocol == C_H265E)
        param->param.h265e_param.H265E_SliceInfoSize = h->param.param.h265e_param.H265E_SliceInfoSize;
	return h;

err_init:
err_validate_parameters:
err_pf_init:
err_validate_common_parameters:
	free(h);
err_malloc_hwicodec:
	return NULL;
}

void hwicodec_deinit(hwicodec_t *h)
{
	if (h) {
		h->pf.deinit(h);
		free(h);
	}
}

int hwicodec_process(hwicodec_t *h, hwicodec_io_t *io)
{
	return h->pf.process(h, io);
}

int hwicodec_request_vbinfo(hwicodec_t *h, hwicodec_vbinfo_t **vbinfo, int *vbnum)
{
	return h->pf.request_vbinfo(h, vbinfo, vbnum);
}

void hwicodec_release_vbinfo(hwicodec_t *h, hwicodec_vbinfo_t *vbinfo)
{
	h->pf.release_vbinfo(h, vbinfo);
}
